//Hung Nguyen 
//Jeremy Sardoma
//Matthew Alcazar

# include <stdlib.h>
# include <stdio.h>  
# include <GL\glut.h>
# include <math.h> 
# include <Windows.h>
# include <string>
# include <sstream>
# include "camera.h"
# include "ship.h"
#include "drawTriModel.cpp"
using namespace std;
//Header/////
void draw();
void resize(int width, int height);
void keydown(unsigned char key, int x, int y);
void keyup(unsigned char key, int x, int y);
void SpecialKeysDown(int key, int xx, int yy);
void SpecialKeysUp(int key, int xx, int yy);
void animate(int value);
void enableLight();
void mouseClick(int button, int state, int x, int y);
void freeTexture( GLuint texture );
GLuint loadRawTexture( const char * filename, int width, int height);
void selectMessage(int msg);

char defaultMessage[] = "Hello.";
char *message = defaultMessage;

Camera Default;
Camera FirstPerson;
Camera BirdsEye;
Camera TopDown;
Camera ThirdPerson;
Camera CamT1;
Camera CamT2;
Camera CamT3;
Camera CamT4;


//Variable
float x_translate;
float y_translate;
float z_translate;
float angle;
float view = 0;
//Quality of the objects
float slices=50;
float stacks=10;
float rings=50;
//Degree per Frame
float angle_t1 = 0;
float angle_p1 = 0;
float angle_t2 = 0;
float angle_p2 = 0;
float angle_p3 = 0;
float angle_t3 = 0;
float angle_p4 = 0;
float angle_p5 = 0;
float angle_p6 = 0;
float angle_t4 = 0;
//limit FPS : TIMEQUANTUM= 40 is 25 FPS
int TIMEQUANTUM = 40;
bool stoppedFrame = false;
int previousTime;
int currentTime;
int elapsedTime;

//Title
int titleFPS=25;
string titleView = "chase";
string titleTurbo = "off";
string titleGravity = "on";
int titleScore = 0;
//Fog stuff

//Ship
Ship mShip;
float ship_angle=0;
Vector shipPos;
//Mouse Position (World Coordinate)
Vector mousePos;
int wrapship = 0;

//KeyBoard array
enum key_state {NOTPUSHED, PUSHED} keyarr[127+100];


//Boudning Spheres
struct BoundingSpheres {
	float radius;
	Vector position;
};
BoundingSpheres boundingT1 [7];
BoundingSpheres boundingT2 [7];
BoundingSpheres boundingT3 [7];
BoundingSpheres boundingT4 [7];

//Texture
int width = 1024, height = 768;   // set texture's width and height values here
char * fileName = "sky.raw";  // set the texture file's name here
char title[50];
int zDepth;
float rotateY = 0;  // angle to rotate teapot on Y
GLuint texture;

bool dontshow = true;
//Main Function
int main(int  argc, char *argv[])  {
	x_translate = 0;
	y_translate =1;
	z_translate=0;
	angle=0;
	
	mousePos = Vector(0,0,0);
	shipPos = Vector(2000,500,-5000);
	mShip = Ship(shipPos.x,shipPos.y,shipPos.z);  
	mShip.angleHorizontal=0;
	mShip.mRotationAxis= Vector(0,1,0);

  // create glut display and window
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
  glutCreateWindow("Tori Tag");
  //Places the Default Camera View
  Default.Move(Float3dVector(0.0, 0.0, 30000.0));
  //Places the BirdsEye Camera View
  BirdsEye.Move(Float3dVector(0.0, 10000.0, 30000.0));
  BirdsEye.RotateX(-20.0);
  
  //Places the FirstPerson Camera View
  FirstPerson.Move(Float3dVector(shipPos.x,shipPos.y+100.0, shipPos.z));
  FirstPerson.RotateY(180.0);  
  
  //Third Person
  ThirdPerson.Move(Float3dVector(shipPos.x,shipPos.y+200,shipPos.z-600));
  ThirdPerson.RotateY(180.0);  
  
  TopDown.Move(Float3dVector(0.0, 40000.0, 0.0));
  TopDown.RotateX(-90.0);
  CamT1.Move(Float3dVector(2000.0,0.0,0.0));
  CamT2.Move(Float3dVector(4000.0,0.0,0.0));
  CamT3.Move(Float3dVector(-8000.0,0.0,0.0));
  CamT4.Move(Float3dVector(-14000.0,0.0,0.0));
  //Lighting
  enableLight();

  // set glut callback functions for event handling
  glutReshapeFunc(resize);    // handle window resize events
  glutDisplayFunc(draw);      // draw the scene
  glutKeyboardFunc(keydown);  
  glutKeyboardUpFunc(keyup);
  glutSpecialFunc(SpecialKeysDown);  //arrow keys
  glutSpecialUpFunc(SpecialKeysUp);  //arrow keys
  glutMouseFunc(mouseClick); //mouse click
  //glutIdleFunc(animate); 
  // Setup the timer to be called one first time
  glutTimerFunc(TIMEQUANTUM, animate, 0);
  //Menu
  int  msg_submenu;
   msg_submenu = glutCreateMenu(selectMessage);
  glutAddMenuEntry("Can Using W instead of CRTL+ UP", 1);
  glutAddMenuEntry("Can Using S instead of CRTL+ DOWN",2);
  glutAddMenuEntry("\"V\" has 3 modes: First Person, Third Person and Stay still camera", 3);
  glutAttachMenu(GLUT_LEFT_BUTTON);
	// Read the current time since glutInit was called
	currentTime = glutGet(GLUT_ELAPSED_TIME);
  // model probably 2 faced -- so cull back face
  glEnable(GL_CULL_FACE);
  glCullFace(GL_BACK);
  drawTriModel(mShip.modelListId, 4.0f);
  //All spheres are have positions that are relative to 
  //	right-handed coordinate system.
  //BoundingSphere T1 
  boundingT1[0].radius = 400;
  boundingT1[0].position = Vector(0,800,0);
  boundingT1[1].radius = 400;
  boundingT1[1].position = Vector(0,-800,0);
  boundingT1[2].radius = 400;
  boundingT1[2].position = Vector(650,150,0);
  boundingT1[3].radius = 400;
  boundingT1[3].position = Vector(650,-150,0);
  boundingT1[4].radius = 400;
  boundingT1[4].position = Vector(-650,150,0);
  boundingT1[5].radius = 400;
  boundingT1[5].position = Vector(-650,-150,0);
  boundingT1[6].radius = 400;
  boundingT1[6].position = Vector(0,0,0);

  //BoundingSphere T2
  boundingT2[0].radius = 550;
  boundingT2[0].position = Vector(0,1100,0);
  boundingT2[1].radius = 550;
  boundingT2[1].position = Vector(0,-1100,0);
  boundingT2[2].radius = 550;
  boundingT2[2].position = Vector(1000,400,0);
  boundingT2[3].radius = 550;
  boundingT2[3].position = Vector(1000,-400,0);
  boundingT2[4].radius = 550;
  boundingT2[4].position = Vector(-1000,400,0);
  boundingT2[5].radius = 550;
  boundingT2[5].position = Vector(-1000,-400,0);
  boundingT2[6].radius = 550;
  boundingT2[6].position = Vector(0,0,0);

  //BoundingSphere T3
  boundingT3[0].radius = 750;
  boundingT3[0].position = Vector(0,1500,0);
  boundingT3[1].radius = 750;
  boundingT3[1].position = Vector(0,-1500,0);
  boundingT3[2].radius = 750;
  boundingT3[2].position = Vector(1300,800,0);
  boundingT3[3].radius = 750;
  boundingT3[3].position = Vector(-1300,800,0);
  boundingT3[4].radius = 750;
  boundingT3[4].position = Vector(1300,-800,0);
  boundingT3[5].radius = 750;
  boundingT3[5].position = Vector(-1300,-800,0);
  boundingT3[6].radius = 750;
  boundingT3[6].position = Vector(0,0,0);
  
  //boundingSphere T4
  boundingT4[0].radius = 650;
  boundingT4[0].position = Vector(0,1300,0);
  boundingT4[1].radius = 650;
  boundingT4[1].position = Vector(0,-1300,0);
  boundingT4[2].radius = 650;
  boundingT4[2].position = Vector(1150,600,0);
  boundingT4[3].radius = 650;
  boundingT4[3].position = Vector(-1150,600,0);
  boundingT4[4].radius = 650;
  boundingT4[4].position = Vector(1150,-600,0);
  boundingT4[5].radius = 650;
  boundingT4[5].position = Vector(-1150,-600,0);
  boundingT4[6].radius = 650;
  boundingT4[6].position = Vector(0,0,0);
  //Texture
  // load texture
   texture = loadRawTexture( fileName, width, height);
   if (width > height) zDepth = width + 200;
      else zDepth = height + 200; 
  // release control to glut / opengl event manager to handle events
  glutMainLoop();  
  // window terminated, exit program, delete objects
  //delete(mSun);  // reclaim memory
  //return (0);
}


void draw()
{
	
// clear display buffer to render
  glClearColor(0,0,0,0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glEnable(GL_DEPTH_TEST);
   // Set Material properties to follow glColor values
   glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);  
   glEnable(GL_COLOR_MATERIAL);  // enable ColorMaterial

  // set mode to model
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
 
  //Window Title
  titleFPS = 1000/TIMEQUANTUM;
  if(mShip.gravity==true) titleGravity="on"; else titleGravity="off";
  if(mShip.turbo==true) titleTurbo="on"; else titleTurbo="off";
  stringstream out;
  out << titleFPS;
  string temp = out.str();
  string title = "Tori Tag : "+temp;
  title += "fps : " + titleView + " : turbo " + titleTurbo + " : gravity "+titleGravity+" : Score ";
  stringstream out1;
  out1 << titleScore;
  temp = out1.str();
  title +=temp;
  title +="   Left Click to more info";
//fps : %s : turbo %s : gravity %s : Score $d", titleFPS, titleView, titleTurbo, titleGravity, titleScore;
  const char * cs = title.c_str ();
   glutSetWindowTitle(cs);
  //Handle Keyboard
	if( keyarr[38] ) {                //UP ARROW
		mShip.MoveForward(10);
		/*FirstPerson.Forward(-10);
		ThirdPerson.Forward(-10);*/
	}
	if( keyarr[40] ) {               //DOWN ARROW
		mShip.MoveForward(-10);
	/*	FirstPerson.Forward(10);
		ThirdPerson.Forward(10);*/
	}
	if( keyarr[37] ) {               //LEFT ARROW
		mShip.RotateHorizontal(5);
		/*FirstPerson.RotateY(5);
		ThirdPerson.RotateY(5);*/
	}
	if( keyarr[39] ) {               //RIGHT ARROW
		mShip.RotateHorizontal(-5);
		/*FirstPerson.RotateY(-5);
		ThirdPerson.RotateY(-5);*/
	}
	if( keyarr[38+100] ) {           //CONTROL UP
		mShip.RotateVertical(-5);
		/*FirstPerson.RotateX(-5);
		ThirdPerson.RotateX(-5);*/
	}
	if( keyarr[40+100] ) {           //CONTROL DOWN
		mShip.RotateVertical(5);
		/*FirstPerson.RotateX(5);
		ThirdPerson.RotateX(5);*/
	}
	if( keyarr[37+100] ) {           //CONTROL RIGHT
		mShip.RotateAt(-5);
		/*FirstPerson.RotateZ(-5);
		ThirdPerson.RotateZ(-5);*/
	}
	if( keyarr[39+100] ) {           //CONTROL LEFT
		mShip.RotateAt(5);
		/*FirstPerson.RotateZ(5);
		ThirdPerson.RotateZ(5);*/
	}
	if( keyarr['w'] ) {
		mShip.RotateVertical(-5);
		//FirstPerson.RotateX(5);
		//ThirdPerson.RotateX(5);
	}
	if( keyarr['s'] ) {
		mShip.RotateVertical(5);
		//FirstPerson.RotateX(-5);
		//ThirdPerson.RotateX(-5);
	}
	//if( keyarr['a'] )
		//mShip.RotateAt(-5,Vector(1,0,0));
	//if( keyarr['d'] )
		//mShip.RotateAt(5,Vector(1,0,0));
	/*if (keyarr['w'] && GLUT_ACTIVE_CTRL)
		mShip.rotate_X;*/
	/*FirstPerson.YRot= -mShip.angle;
	FirstPerson.Position.x=mShip.Pos.x;
	FirstPerson.Position.y=mShip.Pos.y;
	FirstPerson.Position.z=mShip.Pos.z-2000;*/
  // set camera  
  if(view==0)
  { /*
	  gluLookAt(
		0.0, 0.0,  30000.0,    // eye location
		0.0, 0.0,   0.0,    // center location
		0.0, 1.0,   0.0);   // up vector  
	  */
	  TopDown.Render();	  
	  mShip.hidden=false;
  }
  else if (view==1)
  {/*
	   gluLookAt(
		0.0, 500,  5000,    // eye location
		0.0, 0.0,   4000,    // center location
		0.0, 1.0,   0.0);   // up vector  
*/
	  //FirstPerson.Render();
	  titleView = "First Person";
	  int cameray=0;
	  int cameraz=0;
	  int camerax=0;
	 cameray+=(1000*sin(-(mShip.angleVertical*2*3.141592)/360));		 
		 if(mShip.angleVertical<=90 && mShip.angleVertical>=-90)
		 {
			 cameraz+=(1000*cos((mShip.angleHorizontal*2*3.141592)/360));
			camerax+=(1000*sin((mShip.angleHorizontal*2*3.141592)/360));
		 }
		 else
		 {
			cameraz+=-(1000*cos((mShip.angleHorizontal*2*3.141592)/360));
			camerax+=-(1000*sin((mShip.angleHorizontal*2*3.141592)/360));
		 }

	  gluLookAt(
		mShip.Pos.x, mShip.Pos.y,  mShip.Pos.z,    // eye location
		mShip.Pos.x+camerax, mShip.Pos.y+cameray,   mShip.Pos.z+cameraz,    // center location
		0.0, 1.0,   0.0); 
	  mShip.hidden=true;
  }
  else if (view==2)
  {  
	  titleView="Third Person";
	  mShip.hidden=false;
	  int cameray=0;
	  int cameraz=0;
	  int camerax=0;
	 cameray+=(1000*sin(-(mShip.angleVertical*2*3.141592)/360));		 
		 if(mShip.angleVertical<=90 && mShip.angleVertical>=-90)
		 {
			 cameraz+=(1000*cos((mShip.angleHorizontal*2*3.141592)/360));
			camerax+=(1000*sin((mShip.angleHorizontal*2*3.141592)/360));
		 }
		 else
		 {
			cameraz+=-(1000*cos((mShip.angleHorizontal*2*3.141592)/360));
			camerax+=-(1000*sin((mShip.angleHorizontal*2*3.141592)/360));
		 }

	  gluLookAt(
		mShip.Pos.x, mShip.Pos.y+500,  mShip.Pos.z-600,    // eye location
		mShip.Pos.x+camerax, mShip.Pos.y+cameray,   mShip.Pos.z+100+cameraz,    // center location
		0.0, 1.0,   0.0);   // up vector  
	  /*
	  ThirdPerson.Move(Float3dVector(mShip.Pos.x,mShip.Pos.y+200,mShip.Pos.z-600));
	  ThirdPerson.Render();*/
  }
  else if (view==3)
  {   
	  titleView="Stay Still";
	  mShip.hidden=false;
	  ThirdPerson.Render();
  }
  else if(view==5) {
  }
  else if(view==6) { 
	  mShip.hidden=false;
	  CamT1.Render();
	   glTranslatef(0,0,-5000);
	  glRotatef(-angle_t1,x_translate,y_translate,z_translate);
  }
  else if(view==7) { 
	  mShip.hidden=false;
	  CamT2.Render();
	   glTranslatef(0,0,-5000);
	  glRotatef(-angle_t2,x_translate,y_translate,z_translate);
  }
  else if(view==8) { 
	  mShip.hidden=false;
	  CamT3.Render();
	   glTranslatef(0,0,-5000);
	  glRotatef(-angle_t3,x_translate,y_translate,z_translate);
  }
  else if(view==9) { 
	  mShip.hidden=false;
	  CamT4.Render();
	   glTranslatef(0,0,-5000);
	  glRotatef(-angle_t4,x_translate,y_translate,z_translate);
  }
  
  //DRAW OBJECTS
  
	//Sun
	glColor3f(1.0, 0.0, 0.0);
	glutSolidSphere	(1000 , slices , stacks );
	
	//t1	
	glPushMatrix(); //set where to start the current object transformations
	glRotatef(angle_t1,x_translate,y_translate,z_translate);
	glTranslatef(2000,0,0);	
	glColor3f(0, 1.0, 0.0);
	glutSolidTorus(100,400 , slices, rings );
	/*if (dontshow = true){
		if(boundingT1[6].position.magnitude() == boundingT1[6].position.magnitude() - mShip.Pos.magnitude()) {
			glutSolidSphere(boundingT1[6].radius,slices,stacks);
			titleScore += 25;
			dontshow = false;
		}
	}*/
	glPopMatrix(); //end the current object transformations

	//p1
	glPushMatrix(); //set where to start the current object transformations
	glRotatef(angle_p1,x_translate,y_translate,z_translate);
	glTranslatef(-3000,0,0);	
	glColor3f(0.6, 0.6, 1.0);
	glutSolidSphere	(100 , slices , stacks );
	glPopMatrix(); //end the current object transformations

	//t2
	glPushMatrix(); //set where to start the current object transformations
	glRotatef(angle_t2,x_translate,y_translate,z_translate);
	glTranslatef(4000,0,0);	// i dont follow his position
	glColor3f(0.7, 0.3, 0.3);
	glutSolidTorus	(150,550 , slices, rings );
	glPopMatrix(); //end the current object transformations

	//p2
	glPushMatrix(); //set where to start the current object transformations
	glRotatef(angle_p2,x_translate,y_translate,z_translate);
	glTranslatef(0,0,-5000);	
	glColor3f(0.6, 0.6, 1.0);
	glutSolidSphere	(150 , slices , stacks );
	glPopMatrix(); //end the current object transformations

	//p3
	glPushMatrix(); //set where to start the current object transformations
	glRotatef(angle_p3,x_translate,y_translate,z_translate);
	glTranslatef(6000,0,0);	
	glColor3f(0.6, 0.6, 1.0);
	glutSolidSphere	(200 , slices , stacks );
	glPopMatrix(); //end the current object transformations

	//t3
	glPushMatrix(); //set where to start the current object transformations
	glRotatef(angle_t3,x_translate,y_translate,z_translate);
	glTranslatef(-8000,0,0);	
	glColor3f(0.5, 1.0, 0.5);
	glutSolidTorus	(150,750 , slices, rings );
	//glutSolidSphere(750,slices,stacks);
	glPopMatrix(); //end the current object transformations

	//p4
	glPushMatrix(); //set where to start the current object transformations
	glRotatef(angle_p4,x_translate,y_translate,z_translate);
	glTranslatef(0,0,10000);	
	glColor3f(0.6, 0.6, 1.0);
	glutSolidSphere	(250 , slices , stacks );
	glPopMatrix(); //end the current object transformations

	//p5
	glPushMatrix(); //set where to start the current object transformations
	glRotatef(angle_p5,x_translate,y_translate,z_translate);
	glTranslatef(0,0,11000);	
	glColor3f(0.6, 0.6, 1.0);
	glutSolidSphere	(300 , slices , stacks );
	glPopMatrix(); //end the current object transformations

	//p6
	glPushMatrix(); //set where to start the current object transformations
	glRotatef(angle_p6,x_translate,y_translate,z_translate);
	glTranslatef(12000,0,0);	
	glColor3f(0.6, 0.6, 1.0);
	glutSolidSphere	(400 , slices , stacks );
	glPopMatrix(); //end the current object transformations

	//t4
	glPushMatrix(); //set where to start the current object transformations
	glRotatef(angle_t4,x_translate,y_translate,z_translate);
	glTranslatef(-14000,0,0);	
	glColor3f(1.0, 1.0, 0.0);
	glutSolidTorus	(150,650 , slices, rings );
	//glutSolidSphere(650,slices,stacks);
	//glTranslatef(1150,600,0);
	//glutSolidSphere(650,slices,stacks);
	glPopMatrix(); //end the current object transformations

	//ship
	if(wrapship==1)
	{
		mShip.Pos.x=2000*cos((angle_t1*2*3.141592)/360);
		mShip.Pos.y=0;
		mShip.Pos.z=-2000*sin((angle_t1*2*3.141592)/360);
		wrapship=0;
	}
	else if(wrapship==2)
	{
		mShip.Pos.x=4000*cos((angle_t2*2*3.141592)/360);
		mShip.Pos.y=0;
		mShip.Pos.z=-4000*sin((angle_t2*2*3.141592)/360);
		wrapship=0;
	}
	else if(wrapship==3)
	{
		mShip.Pos.x=-8000*cos((angle_t3*2*3.141592)/360);
		mShip.Pos.y=0;
		mShip.Pos.z=8000*sin((angle_t3*2*3.141592)/360);
		wrapship=0;
	}
	else if(wrapship==4)
	{
		mShip.Pos.x=-14000*cos((angle_t4*2*3.141592)/360);
		mShip.Pos.y=0;
		mShip.Pos.z=14000*sin((angle_t4*2*3.141592)/360);
		wrapship=0;
	}
	mShip.Draw();
	// 6 Quads
	glEnable( GL_TEXTURE_2D );
    glBindTexture( GL_TEXTURE_2D, texture );

	glPushMatrix(); 	
	glColor3f(1.0, 1.0, 1.0);
	glBegin(GL_QUADS);
	glTexCoord2d(0.0,1.0);glVertex3f(75000, 75000, 75000);
	glTexCoord2d(0.0,0.0);glVertex3f(75000,-75000,75000);
	glTexCoord2d(1.0,0.0);glVertex3f(-75000,-75000,75000);
	glTexCoord2d(1.0,1.0);glVertex3f(-75000,75000,75000);
	glEnd();		
	glPopMatrix(); 

	glPushMatrix(); 
	glColor3f(1.0, 1.0, 1.0);
	glBegin(GL_QUADS);
	glTexCoord2d(0.0,1.0);glVertex3f(-75000,-75000,-75000);
	glTexCoord2d(0.0,0.0);glVertex3f(75000,-75000,-75000);
	glTexCoord2d(1.0,0.0);glVertex3f(75000, 75000, -75000);
	glTexCoord2d(1.0,1.0);glVertex3f(-75000,75000,-75000);
	glEnd();
	glPopMatrix();

	glPushMatrix(); 
	glColor3f(1.0, 1.0, 1.0);
	glBegin(GL_QUADS);
	glTexCoord2d(0.0,1.0);glVertex3f(75000,-75000,-75000);
	glTexCoord2d(0.0,0.0);glVertex3f(75000, -75000, 75000);
	glTexCoord2d(1.0,0.0);glVertex3f(75000, 75000, 75000);
	glTexCoord2d(1.0,1.0);glVertex3f(75000, 75000, -75000);
	glEnd();
	glPopMatrix();

	glPushMatrix(); 
	glColor3f(1.0, 1.0, 1.0);
	glBegin(GL_QUADS);
	glTexCoord2d(0.0,1.0);glVertex3f(-75000,-75000,-75000);
	glTexCoord2d(0.0,0.0);glVertex3f(-75000, 75000, -75000);
	glTexCoord2d(1.0,0.0);glVertex3f(-75000, 75000, 75000);
	glTexCoord2d(1.0,1.0);glVertex3f(-75000, -75000, 75000);
	glEnd();
	glPopMatrix();

	glPushMatrix();
	glColor3f(1.0, 1.0, 1.0);
	glBegin(GL_QUADS);
	//glNormal3f(0.0, 0.0, 1.0);
	glTexCoord2d(0.0,1.0); glVertex3f(-75000,75000,-75000);
	glTexCoord2d(0.0,0.0);glVertex3f(-75000, 75000, 75000);
	glTexCoord2d(1.0,0.0); glVertex3f(75000, 75000, 75000);
	glTexCoord2d(1.0,1.0);glVertex3f(75000, 75000, -75000);
	glEnd();
	glPopMatrix();

	glPushMatrix(); 
	glColor3f(1.0, 1.0, 1.0);
	glBegin(GL_QUADS);
	glTexCoord2d(0.0,1.0);glVertex3f(-75000,-25000,-75000);
	glTexCoord2d(0.0,0.0);glVertex3f(-75000,-25000, 75000);
	glTexCoord2d(1.0,0.0);glVertex3f(75000,-25000,75000);
	glTexCoord2d(1.0,1.0);glVertex3f(75000,-25000, -75000);
	glEnd();
	glPopMatrix();

	
   glDisable(GL_TEXTURE_2D );
	//Sleep(5);
	glutSwapBuffers();    // swap off screen and display buffers
  //printf("draw\n");
}

void resize(int width, int height) {
  glViewport(0, 0, width, height);
  // set mode to projection
  glMatrixMode(GL_PROJECTION); 
  glLoadIdentity();
  gluPerspective(45.0, (float)width / (float)height, 1.0, 100000.0);
  // set mode to model
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  printf("resize\n");
  }

void keydown(unsigned char key, int x, int y) {  
   //can always adjust the amount of distance travelled in the parameters
	switch (key) {
	   case 27: 
		   PostQuitMessage(0); 
		   break;
	   case '0':
			view = 0;
			printf("\n Top Down View.");
			break;
	  case '1':
			wrapship=1;
			break;
	  case '2':
			wrapship=2;
			break;
	  case '3':
			wrapship=3;
			break;
	  case '4':
			wrapship=4;
			break;	 
	  case '6':
		    view = 6;
			printf("\n Tori 1 View.");
			break;
	  case '7':
		    view = 7;
			printf("\n Tori 2 View.");
			break;
	  case '8':
		    view = 8;
			printf("\n Tori 3 View.");
			break;
	  case '9':
		    view = 9;
			printf("\n Tori 4 View.");
			break;	 

	//Ship
	   case 'a':
		   keyarr[int('a')] = PUSHED;
		   break;
		case 'd':
			keyarr[int('d')] = PUSHED;
		   break;
		case 'w':			
			keyarr[int('w')] = PUSHED;
		   break;
		case 's':
			keyarr[int('s')] = PUSHED;
		   break;

		case 'q':
		   mShip.Pos.y+=10;
		   break;
		case 'e':
		   mShip.Pos.y-=10;
		   break;
		case 'o':
			mShip.Pos.x+=10;
			break;
		case 'p':
			mShip.Pos.x-=10;
			break;
		case 'z':  //go up
			CamT1.Up(4.0);
			CamT2.Up(4.0);
			CamT3.Up(4.0);
			CamT4.Up(4.0);
			draw();
			break;
		case 'x': //go down
			CamT1.Up(-4.0);
			CamT2.Up(-4.0);
			CamT3.Up(-4.0);
			CamT4.Up(-4.0);
			draw();
			break;
		case 'h' :
			FirstPerson.RotateY(4.0);
			CamT1.RotateY(4.0);
			CamT2.RotateY(4.0);
			CamT3.RotateY(4.0);
			CamT4.RotateY(4.0);
			draw();
			break;
		case 'k' :
			FirstPerson.RotateY(-4.0);
			CamT1.RotateY(-4.0);
			CamT2.RotateY(-4.0);
			CamT3.RotateY(-4.0);
			CamT4.RotateY(-4.0);
			draw();
			break;
		case 'u' :
			FirstPerson.Forward(-50.0);
			draw();
			break;
		case 'j' :
			FirstPerson.Forward(50.0);
			draw();
			break;
		
	//real
		case 'v' : view++; if(view>3) view=1; printf("\nChange Camera to : %f",view); break;
		case 't': //next TQ value
			if(TIMEQUANTUM==100){ TIMEQUANTUM=40;printf("\nTIMEQUANTUM : %d",TIMEQUANTUM);}
			else if(TIMEQUANTUM==40) {TIMEQUANTUM=20;printf("\nTIMEQUANTUM : %d",TIMEQUANTUM);}
			else if(TIMEQUANTUM==20) {TIMEQUANTUM=100; printf("\nTIMEQUANTUM : %d",TIMEQUANTUM);}
			break;
		case 32: //Spacebar
			if(stoppedFrame==true) {stoppedFrame=false;glutTimerFunc(TIMEQUANTUM, animate, 0);break;}
			else stoppedFrame=true;
			break;
		case 'g' : 
			mShip.gravity = !mShip.gravity;

			break;
		case 'f' : 
			mShip.turbo = !mShip.turbo;
			FirstPerson.turbo = !FirstPerson.turbo;
			ThirdPerson.turbo = !ThirdPerson.turbo;
			break;
		default   :  printf("\nonly 1, 2, or 3 keys set size of cube\n x: %f, y:%f, z:%f, angle:%f",x_translate,y_translate,z_translate,angle); 
   }
   //glutPostRedisplay();  // call displayFunc
}
void keyup(unsigned char k, int x, int y)
{
	if(k == 'd')
	keyarr['d'] = NOTPUSHED;
	if(k == 'w')
	keyarr['w'] = NOTPUSHED;
	if(k == 's')
	keyarr['s'] = NOTPUSHED;
	if(k == 'a')
	keyarr['a'] = NOTPUSHED;
}
void SpecialKeysDown(int key, int xx, int yy) {
	/*switch (key) {
		case GLUT_KEY_LEFT :
			FirstPerson.RotateY(4.0);
			CamT1.RotateY(4.0);
			CamT2.RotateY(4.0);
			CamT3.RotateY(4.0);
			CamT4.RotateY(4.0);
			draw();
			break;
		case GLUT_KEY_RIGHT :
			FirstPerson.RotateY(-4.0);
			CamT1.RotateY(-4.0);
			CamT2.RotateY(-4.0);
			CamT3.RotateY(-4.0);
			CamT4.RotateY(-4.0);
			draw();
			break;
		case GLUT_KEY_UP :
			FirstPerson.Forward(-50.0);
			draw();
			break;
		case GLUT_KEY_DOWN :
			FirstPerson.Forward(50.0);
			draw();
			break;
		
	}*/
	//WITHOUT CTRL BUTTON
	if(key==GLUT_KEY_UP && glutGetModifiers() != GLUT_ACTIVE_CTRL)
	{
		keyarr[38] = PUSHED;
	}
	if(key==GLUT_KEY_DOWN && glutGetModifiers() != GLUT_ACTIVE_CTRL)
	{
		keyarr[40] = PUSHED;
	}
	if(key==GLUT_KEY_LEFT && glutGetModifiers() != GLUT_ACTIVE_CTRL)
	{
		keyarr[37] = PUSHED;
	}
	if(key==GLUT_KEY_RIGHT && glutGetModifiers() != GLUT_ACTIVE_CTRL)
	{
		keyarr[39] = PUSHED;
	}

	//WITH CTRL BUTTON
	if(key==GLUT_KEY_UP && glutGetModifiers() == GLUT_ACTIVE_CTRL)
	{
		keyarr[38+100] = PUSHED;
	}
	if(key==GLUT_KEY_DOWN && glutGetModifiers() == GLUT_ACTIVE_CTRL)
	{
		keyarr[40+100] = PUSHED;
	}
	if(key==GLUT_KEY_LEFT && glutGetModifiers() == GLUT_ACTIVE_CTRL)
	{
		keyarr[37+100] = PUSHED;
	}
	if(key==GLUT_KEY_RIGHT && glutGetModifiers() == GLUT_ACTIVE_CTRL)
	{
		keyarr[39+100] = PUSHED;
	}
}
void SpecialKeysUp(int key, int xx, int yy) {
	if(key==GLUT_KEY_UP && glutGetModifiers() != GLUT_ACTIVE_CTRL)
	{
		keyarr[38+100] = NOTPUSHED;
		keyarr[38] = NOTPUSHED;
	}
	if(key==GLUT_KEY_DOWN && glutGetModifiers() != GLUT_ACTIVE_CTRL)
	{
		keyarr[40+100] = NOTPUSHED;
		keyarr[40] = NOTPUSHED;
	}
	if(key==GLUT_KEY_LEFT && glutGetModifiers() != GLUT_ACTIVE_CTRL)
	{
		keyarr[37+100] = NOTPUSHED;
		keyarr[37] = NOTPUSHED;
	}
	if(key==GLUT_KEY_RIGHT && glutGetModifiers() != GLUT_ACTIVE_CTRL)
	{
		keyarr[39+100] = NOTPUSHED;
		keyarr[39] = NOTPUSHED;
	}

	//WITH CTRL BUTTON
	if(key==GLUT_KEY_UP && glutGetModifiers() == GLUT_ACTIVE_CTRL)
	{
		keyarr[38+100] = NOTPUSHED;
		keyarr[38] = NOTPUSHED;
	}
	if(key==GLUT_KEY_DOWN && glutGetModifiers() == GLUT_ACTIVE_CTRL)
	{
		keyarr[40+100] = NOTPUSHED;
		keyarr[40] = NOTPUSHED;
	}
	if(key==GLUT_KEY_LEFT && glutGetModifiers() == GLUT_ACTIVE_CTRL)
	{
		keyarr[37+100] = NOTPUSHED;
		keyarr[37] = NOTPUSHED;
	}
	if(key==GLUT_KEY_RIGHT && glutGetModifiers() == GLUT_ACTIVE_CTRL)
	{
		keyarr[39+100] = NOTPUSHED;
		keyarr[39] = NOTPUSHED;
	}
}
void animate(int value)
{
	if(stoppedFrame==false){
		// setups the timer to be called again
		glutTimerFunc(TIMEQUANTUM, animate, 0);
	}

	// Get the time when the previous frame was rendered
	previousTime = currentTime;

	// Get the current time (in milliseconds) and calculate the elapsed time
	currentTime = glutGet(GLUT_ELAPSED_TIME);
	elapsedTime = currentTime - previousTime;

	//increase angles
	//test
	angle+=0.5;	if (angle>360) angle=0;
	//real
	angle_t1+=0.240;	if (angle_t1>360) angle_t1=angle_t1-360;
	angle_p1+=0.120;	if (angle_p1>360) angle_p1=angle_p1-360;
	angle_t2+=0.080;	if (angle_t2>360) angle_t2=angle_t2-360;
	angle_p2+=0.072;	if (angle_p2>360) angle_p2=angle_p2-360;
	angle_p3+=0.066;	if (angle_p3>360) angle_p3=angle_p3-360;
	angle_t3+=0.060;	if (angle_t3>360) angle_t3=angle_t3-360;	
	angle_p4+=0.056;	if (angle_p4>360) angle_p4=angle_p4-360;
	angle_p5+=0.053;	if (angle_p5>360) angle_p5=angle_p5-360;
	angle_p6+=0.051;	if (angle_p6>360) angle_p6=angle_p6-360;
	angle_t4+=0.048;	if (angle_t4>360) angle_t4=angle_t4-360;
	
	
	// forces a redraw with the new angle
	glutPostRedisplay();

	//printf("FPS: %4.2f\n", 1000.0f / elapsedTime);
}


void enableLight()
{	
   //Enable Lighting
  glClearDepth(1);
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);

	// Create light components
  GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };
  GLfloat diffuseLight[] = { 0.8f, 0.8f, 0.8, 1.0f };
  GLfloat specularLight[] = { 0.5f, 0.5f, 0.5f, 1.0f };
  GLfloat position[] = { 1000.0f, 1000.0f, 1000.0f, 0.0f };
  //GLfloat position[] = { -1.5f, 1.0f, -4.0f, 1.0f };

	// Assign created components to GL_LIGHT0
  glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
  glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
  glLightfv(GL_LIGHT0, GL_POSITION, position);

 
  // Evaluate the reflective properties of the material
  float colorBlue[] = { 0.0f, 0.0f, 1.0f, 1.0f };
  glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, colorBlue);

  // Draw a polygon with current material properties being set
  glBegin(GL_TRIANGLES);
  glVertex3f(-1.0f, 0.0f, 0.0f);
  glVertex3f(0.0f, -1.0f, 0.0f);
  glVertex3f(1.0f, 0.0f, 0.0f);
  glEnd();
  glEnable(GL_COLOR_MATERIAL);
}

void mouseClick(int button, int state, int x, int y)
{
	//if ((button == GLUT_LEFT_BUTTON) && (state == GLUT_DOWN))
	//{
	//	GLint viewport[4];
	//	GLdouble modelview[16],projection[16];
	//	GLfloat wx=x,wy,wz;
	//	glGetIntegerv(GL_VIEWPORT,viewport);
	//	y=viewport[3]-y;
	//	wy=y;
	//	glGetDoublev(GL_MODELVIEW_MATRIX,modelview);
	//	glGetDoublev(GL_PROJECTION_MATRIX,projection);
	//	glReadPixels(x,y,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,&wz);
	//	gluUnProject(wx,wy,wz,modelview,projection,viewport,&(mousePos.x),&(mousePos.y),&(mousePos.z));
	//	//mShip.RotateToward(mousePos);
	//	mShip.Pos=mousePos;
	//}
}
///Texture
   
void freeTexture( GLuint texture ) {  glDeleteTextures( 1, &texture ); }


GLuint loadRawTexture( const char * filename, int width, int height) {
  unsigned char * data;
  FILE * file;
  int readResult;

  // open texture data
  file = fopen( filename, "rb" );
  if ( file == NULL ) {
     printf("File %s can't be opened\n");
     return 0;}
  // allocate buffer -- 3 bytes / texel -- rgb
  data = (unsigned char *) malloc( width * height * 3 );
  // read texture data
  readResult = fread( data, width * height * 3, 1, file );
  if (readResult != 1) {
     printf("File %s was not read correctly\n");
     return 0; }
  fclose( file );
  
  glGenTextures( 1, &texture ); // generate the texture with the loaded data
  glBindTexture( GL_TEXTURE_2D, texture ); //bind the texture  
  glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); //set texture environment parameters
  // set texture parameters
  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
  // generate the texture
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, 
	  GL_RGB, GL_UNSIGNED_BYTE, data);
  free( data ); //free the texture
  return texture; //return whether it was successfull
}

void selectMessage(int msg)
{
  switch (msg) {
  case 1:
    message = "abcdefghijklmnop";
    break;
  case 2:
    message = "ABCDEFGHIJKLMNOP";
    break;
  }
}